package org.jeecg.modules.platformMasterEndPoint.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.modules.jx.constant.FileConstants;
import org.jeecg.modules.jx.utils.JxCryptUtil;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxSiteMenuDo;
import org.jeecg.modules.miniAppCustomerEndPoint.entity.JxSiteStoreDo;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxSiteMenuMapper;
import org.jeecg.modules.miniAppCustomerEndPoint.mapper.JxSiteStoreMapper;
import org.jeecg.modules.platformMasterEndPoint.entity.*;
import org.jeecg.modules.platformMasterEndPoint.mapper.JxFoodRepositoryMapper;
import org.jeecg.modules.platformMasterEndPoint.mapper.JxStoreRepositoryMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

import static org.jeecg.modules.miniAppMerchantEndPoint.constant.JxMerchantMiniAppConstants.MERCHANT_LOGIN_TOKEN_PREFIX;

@Api(tags = "店铺管理")
@RestController
@RequestMapping("/jx/jxStoreManage")
@Slf4j
public class JxStoreManageController {

    @Autowired
    private JxStoreRepositoryMapper jxStoreRepositoryMapper;

    @Autowired
    private JxFoodRepositoryMapper jxFoodRepositoryMapper;

    @Autowired
    private JxSiteStoreMapper jxSiteStoreMapper;

    @Autowired
    private JxSiteMenuMapper jxSiteMenuMapper;

    @Autowired
    private JxCryptUtil jxCryptUtil;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 接口使用场景
     * 1. 店铺&菜品管理页面，点击 【新增店铺】按钮，跳转至 新增店铺页面，填写完店铺基本信息（店主信息，店铺描述，店铺菜品类型，营业时间，合作价等），点击【保存】按钮，调用此接口，不传递店铺id
     * 2. 点击【编辑】跳转到 新增/编辑 店铺信息页面，修改完信息后，点击 【保存】，调用此接口，传递 店铺id
     * @param storeRepositoryVo
     * @return
     */
    @ApiOperation("平台管理员或站长 向店铺信息库中录入一个新的店铺")
    @PostMapping("/addOrEditStoreInfo")
    public Result<?> addOrEditStoreInfo(@RequestBody() JxStoreRepositoryVo storeRepositoryVo) throws Exception {

        if (storeRepositoryVo.getId() == null || storeRepositoryVo.getId().isEmpty()) {
            // 由于新增和编辑店铺信息，复用同一个接口，当编辑时，请求参数中无 storeId
            // 根据店主名称和店铺名称进行查询，不允许录入重复的店铺信息
            List<JxStoreRepositoryDo> list1 = jxStoreRepositoryMapper.selectList(new LambdaQueryWrapper<JxStoreRepositoryDo>()
                    .eq(JxStoreRepositoryDo::getStoreName, storeRepositoryVo.getStoreName())
                    .eq(JxStoreRepositoryDo::getMerchantName, storeRepositoryVo.getMerchantName()));
            if (list1 != null & list1.size() > 0) {
                return Result.error(450, "店主: " + storeRepositoryVo.getMerchantName() + ", 店铺名称: " + storeRepositoryVo.getStoreName() + "已存在店铺信息库中，不能录入重复的店铺");
            }
            JxStoreRepositoryDo storeRepositoryDo = buildStoreRepositoryInfo(storeRepositoryVo);

            int count = jxStoreRepositoryMapper.insert(storeRepositoryDo);
            // 由于每个店铺的图片，都是存放在以店铺id为文件夹的 目录下，因此需要先向 jx_store_repository 表中添加一条店铺记录，才会生成店铺id，然后再为该店铺创建目录，将图片从临时目录移动到 正式目录中
            String finalLogoUrl = "";
            if (storeRepositoryVo.getLogo() != null && !storeRepositoryVo.getLogo().isEmpty()) {
                // 由于涉及到对图片进行移动，因此需要先检查上传的图片名称是否为空，避免出现文件IO异常
                finalLogoUrl = moveAndGenerateImageUrl(storeRepositoryVo.getLogo(), storeRepositoryDo.getId(), "logo");
            } else {
                log.warn("新增店铺 {}, {} 的信息时，传递的店铺logo图片既不是文件名，也不是已经上传后的url，为null或空字符串，请检查请求参数", storeRepositoryDo.getId(), storeRepositoryDo.getStoreName());
            }
            String finalQualificationUrl = "";
            if (storeRepositoryVo.getLogo() != null && !storeRepositoryVo.getLogo().isEmpty()) {
                // 由于涉及到对图片进行移动，因此需要先检查上传的图片名称是否为空，避免出现文件IO异常
                finalQualificationUrl = moveAndGenerateImageUrl(storeRepositoryVo.getQualification(), storeRepositoryDo.getId(), "qualification");
            } else {
                log.warn("新增店铺 {}, {} 的信息时，传递的店铺资质图片既不是文件名，也不是已经上传后的url，为null或空字符串，请检查请求参数", storeRepositoryDo.getId(), storeRepositoryDo.getStoreName());
            }
            JxStoreRepositoryDo storeRepositoryDo2 = new JxStoreRepositoryDo();
            storeRepositoryDo2.setId(storeRepositoryDo.getId());
            storeRepositoryDo2.setLogo(finalLogoUrl);
            storeRepositoryDo2.setQualifications(finalQualificationUrl);
            jxStoreRepositoryMapper.updateById(storeRepositoryDo2);

            HashMap<String, Object> resultData = new HashMap<>();
            if (count == 1) {
                resultData.put("storeId", storeRepositoryDo.getId());
                log.info("新增店铺成功，店铺id: {}", storeRepositoryDo.getId());
                return Result.ok(resultData);
            } else {
                return Result.error("录入新店铺失败，联系后台技术人员进行定位");
            }
        } else {
            // 由于新增和编辑店铺信息，复用同一个接口，当编辑时，请求参数中会带上 storeId
            JxStoreRepositoryDo storeRepositoryDo = buildStoreRepositoryInfo(storeRepositoryVo);
            storeRepositoryDo.setId(storeRepositoryVo.getId());

            // 由于涉及到对图片进行移动，因此需要检查上传的图片名称是否为空，避免出现文件IO异常
            if (storeRepositoryVo.getLogo() != null && !storeRepositoryVo.getLogo().isEmpty()) {
                String finalLogoUrl = moveAndGenerateImageUrl(storeRepositoryVo.getLogo(), storeRepositoryVo.getId(), "logo");
                storeRepositoryDo.setLogo(finalLogoUrl);
            } else {
                log.warn("编辑店铺 {}, {} 的信息时，传递的店铺logo图片既不是文件名，也不是已经上传后的url，为null或空字符串，请检查请求参数", storeRepositoryDo.getId(), storeRepositoryDo.getStoreName());
            }

            // 由于涉及到对图片进行移动，因此需要检查上传的图片名称是否为空，避免出现文件IO异常
            if (storeRepositoryVo.getQualification() != null && !storeRepositoryVo.getQualification().isEmpty()) {
                String finalQualificationUrl = moveAndGenerateImageUrl(storeRepositoryVo.getQualification(), storeRepositoryVo.getId(), "qualification");
                storeRepositoryDo.setQualifications(finalQualificationUrl);
            } else {
                log.warn("编辑店铺 {}, {} 的信息时，传递的店铺资质图片既不是文件名，也不是已经上传后的url，为null或空字符串，请检查请求参数", storeRepositoryDo.getId(), storeRepositoryDo.getStoreName());
            }

            int count = jxStoreRepositoryMapper.updateById(storeRepositoryDo);

            if (count == 1) {
                log.info("店铺{} 信息更新成功", storeRepositoryVo.getId());
                return Result.ok();
            } else {
                return Result.error("店铺信息更新失败，联系后台技术人员进行定位");
            }
        }
    }

    /**
     * 将图片从临时上传路径 移动到 正式目录，并生成 url
     * @param imageName
     * @param storeId
     * @param imageTypeDir 同一个店铺有多种类型的图片，比如 店铺logo，店铺资质，店铺中菜品图片，还有当前没有在页面上要求提供的 门店内图片，此字段的取值为 logo , qualification
     * @return
     * @throws Exception
     */
    private String moveAndGenerateImageUrl(String imageName, String storeId, String imageTypeDir) throws Exception {

        String finalImageUrl = "";
        File storeImageUploadDir = new File(Paths.get(FileConstants.IMAGE_FOOD_UPLOAD_DIR , storeId , imageTypeDir).toUri());
        if (!storeImageUploadDir.exists()) {
            storeImageUploadDir.mkdirs();
        }
        if (imageName.trim().startsWith("http")) {
            log.info("调用参数中的图片链接为: {}, 是url，属于编辑菜品信息场景，且没有更新图片，不需要重新移动图片，不需要重新生成图片url", imageName);
            finalImageUrl = imageName;
        } else {
            log.info("调用参数中的图片链接为: {},不是url ，需要移动图片，并生成图片url", imageName);
            try {
                Path tempPath =  Paths.get(FileConstants.FILE_UPLOAD_TEMP_DIR , imageName);
                Path imagePath = Paths.get(storeImageUploadDir.getAbsolutePath(), imageName);
                Files.move(tempPath, imagePath);
                log.info("temp: {}, imagePath: {}", tempPath, imagePath);
                finalImageUrl = FileConstants.IMAGE_URL_BASE + storeId + "/" + imageTypeDir + "/" + imageName;
            } catch (IOException e) {
                log.error("录入新菜品时，将临时目录下的图片移动到 正式目录失败");
                log.error("{}", e);
                throw new Exception("录入新菜品时，将临时目录下的图片移动到 正式目录失败");
            }
        }

        return finalImageUrl;
    }

    /**
     * 创建 JxStoreRepositoryDo 对象，并填充各个字段的值
     * 使用场景
     * 1. 新增或更新店铺信息时，前端调用接口时，会传递店铺信息，包括需要修改的和没有修改的，为了简化接口传参定义，更新时，属性值无论是否有更新，都一起传递给后端，后端直接更新整条记录，不用再去区分更新那些字段，不更新那些字段
     * @param storeRepositoryVo
     * @return
     */
    private JxStoreRepositoryDo buildStoreRepositoryInfo(JxStoreRepositoryVo storeRepositoryVo) {
        JxStoreRepositoryDo storeRepositoryDo = new JxStoreRepositoryDo();
        storeRepositoryDo.setStoreName(storeRepositoryVo.getStoreName());
        storeRepositoryDo.setStoreDescription(storeRepositoryVo.getStoreDescription());
        storeRepositoryDo.setLogo(storeRepositoryVo.getLogo());
        storeRepositoryDo.setStorePrice(storeRepositoryVo.getStorePrice());
        storeRepositoryDo.setMerchantName(storeRepositoryVo.getMerchantName());
        storeRepositoryDo.setMerchantIdNum(storeRepositoryVo.getMerchantIdNum());
        storeRepositoryDo.setMerchantPhone(storeRepositoryVo.getMerchantPhone());
        if (storeRepositoryVo.getLoginPassword() != null && !storeRepositoryDo.getMerchantLoginPasswd().isEmpty()) {
            // 当编辑店铺信息时，当传递的 登录密码不为空或空字符串，则表示 重置密码，此时重新对新密码进行加密，并保存到数据库中
            storeRepositoryDo.setMerchantLoginPasswd(jxCryptUtil.encryptMerchantPassword(storeRepositoryVo.getLoginPassword()));
        }
        storeRepositoryDo.setMerchantWechatNum(storeRepositoryVo.getMerchantWechatNum());
        storeRepositoryDo.setStoreAddress(storeRepositoryVo.getStoreAddress());
        storeRepositoryDo.setLongitude(storeRepositoryVo.getLongitude());
        storeRepositoryDo.setLatitude(storeRepositoryVo.getLatitude());
        storeRepositoryDo.setCategoryId(storeRepositoryVo.getCategoryId());
        storeRepositoryDo.setCategoryName(storeRepositoryVo.getCategoryName());
        if (storeRepositoryVo.getFoodType() != null){
            storeRepositoryDo.setFoodTypes(storeRepositoryVo.getFoodType().toJSONString());
        }
        storeRepositoryDo.setBusinessStart(storeRepositoryVo.getBusinessStart());
        storeRepositoryDo.setBusinessEnd(storeRepositoryVo.getBusinessEnd());
        storeRepositoryDo.setCreateTime(new Date());
        return storeRepositoryDo;
    }

    /**
     * 展示状态为正常营业的店铺列表, 仅返回某个站点没有挑选的店铺，因此请求参数中要去传递siteId，仅返回 店铺仓库 表，没有给该站点配置的店铺
     * 接口调用场景
     * 1. 站点管理页面，点击 【配置店铺】按钮，跳转到 为站点配置店铺的页面，点击 【新增店铺】按钮，弹出可供选择的店铺列表，平台管理员或站长 挑选一个或多个店铺，配置给该站点
     * 2. 在可供挑选的店铺页面中，输入 店铺名搜索店铺 进行搜索符合条件的店铺名
     * @return
     */
    @GetMapping("/queryAvailableStoresWithKeyword")
    public Result<?> queryAvailableStoresWithKeyword(
            @RequestParam("siteId") String siteId,
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {

        List<JxSiteStoreDo> siteStoreDos = jxSiteStoreMapper.selectList(new LambdaQueryWrapper<JxSiteStoreDo>().eq(JxSiteStoreDo::getDelFlag, 0).eq(JxSiteStoreDo::getSiteId, siteId).select(JxSiteStoreDo::getId));
        List<String> alreadyChoosedStores = siteStoreDos.stream().map(siteStoreDo -> siteStoreDo.getId()).collect(Collectors.toList());

        Page<JxStoreRepositoryDo> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<JxStoreRepositoryDo> queryWrapper = new LambdaQueryWrapper<>();
        if (keyword == null || keyword.isEmpty()) {
            // 当点击【新增店铺】按钮，跳转到 可供挑选的店铺页面时，不传递keyword，分页加载所有del_flag为0的店铺
            queryWrapper.eq(JxStoreRepositoryDo::getDelFlag, 0).notIn(JxStoreRepositoryDo::getId, alreadyChoosedStores);
        } else {
            // 当在 可供挑选的店铺页面中，输入 店铺名搜索店铺时，传递keyword，模糊搜索符合条件的，del_flag为0的店铺
            queryWrapper.eq(JxStoreRepositoryDo::getDelFlag, 0).like(JxStoreRepositoryDo::getStoreName, keyword).notIn(JxStoreRepositoryDo::getId, alreadyChoosedStores);
        }
        Page<JxStoreRepositoryDo> pageList = jxStoreRepositoryMapper.selectPage(page,
                queryWrapper.select(JxStoreRepositoryDo::getId, JxStoreRepositoryDo::getStoreName, JxStoreRepositoryDo::getCategoryName,
                        JxStoreRepositoryDo::getStorePrice, JxStoreRepositoryDo::getStoreAddress));

        JSONObject resultData = new JSONObject();
        JSONArray storeList = new JSONArray();
        for (int k = 0 ; k < pageList.getRecords().size(); k ++) {
            JxStoreRepositoryDo oneStoreRepository = pageList.getRecords().get(k);
            JSONObject formatedStoreInfo = new JSONObject();
            formatedStoreInfo.put("storeId", oneStoreRepository.getId());
            formatedStoreInfo.put("storeName", oneStoreRepository.getStoreName());
            formatedStoreInfo.put("categoryName", oneStoreRepository.getCategoryName());
            formatedStoreInfo.put("storePrice", oneStoreRepository.getStorePrice());
            formatedStoreInfo.put("storeAddress", oneStoreRepository.getStoreAddress());
            storeList.add(formatedStoreInfo);
        }

        resultData.put("availableStores", storeList);
        resultData.put("totalPages", pageList.getPages());
        resultData.put("totalCount", pageList.getTotal());
        resultData.put("currentPage", pageList.getCurrent());

        return Result.ok(resultData);
    }

    /**
     * 接口使用场景
     * 1. 站点管理页面，当为站点挑选店铺时，展示可供挑选的店铺的弹窗中，有关键字输入框，可以根据店铺名关键字进行搜索；因为后期合作的店铺会很多，为了快速找到想要合作的店铺，因此 为挑选店铺的弹窗添加搜索框
     * 2. 店铺&菜品管理页面，通过搜索框中输入关键字，搜索目标店铺，展示在 店铺管理页面 的表格中，然后 进行 查看，编辑，删除，编辑菜品等操作；
     * 当请求参数中无 keyword 时，keyword值为null，会导致 like() 函数拼接成 siteId like '%null%' 这样的语句，使用 @RequestParam注解的 default参数，当url中无这两个参数时，给个默认空字符串的值
     * 这样 like() 将会拼接成 like '%%' ，可以匹配所有的行
     *
     * @param keyword
     * @param pageNo
     * @param pageSize
     * @return
     */
    @ApiOperation("根据店铺名称 关键字，分页查询适合供餐的店铺列表")
    @GetMapping("/queryStoreByKeyword")
    public Result<?> queryStoreByKeyword(
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {

        Page<JxStoreRepositoryDo> page = new Page<>(pageNo, pageSize);
        Page<JxStoreRepositoryDo> pageList = jxStoreRepositoryMapper.selectPage(page, new LambdaUpdateWrapper<JxStoreRepositoryDo>().like(JxStoreRepositoryDo::getStoreName, keyword));
        HashMap<String, Object> resultMap = new HashMap<>();
        List<JxStoreRepositoryVo> stores = new ArrayList<>();
        for (int i = 0; i < pageList.getRecords().size(); i++) {
            JxStoreRepositoryDo storeRepositoryDo = pageList.getRecords().get(i);
            JxStoreRepositoryVo storeRepositoryVo = new JxStoreRepositoryVo();
            storeRepositoryVo.setId(storeRepositoryDo.getId());
            storeRepositoryVo.setStoreName(storeRepositoryDo.getStoreName());
            storeRepositoryVo.setStoreDescription(storeRepositoryDo.getStoreDescription());
            storeRepositoryVo.setLogo(storeRepositoryDo.getLogo());
            storeRepositoryVo.setQualification(storeRepositoryDo.getQualifications());
            storeRepositoryVo.setStorePrice(storeRepositoryDo.getStorePrice());
            storeRepositoryVo.setMerchantName(storeRepositoryDo.getMerchantName());
            storeRepositoryVo.setMerchantIdNum(storeRepositoryDo.getMerchantIdNum());
            storeRepositoryVo.setMerchantPhone(storeRepositoryDo.getMerchantPhone());
            storeRepositoryVo.setMerchantWechatNum(storeRepositoryDo.getMerchantWechatNum());
            storeRepositoryVo.setStoreAddress(storeRepositoryDo.getStoreAddress());
            storeRepositoryVo.setLongitude(storeRepositoryDo.getLongitude());
            storeRepositoryVo.setLatitude(storeRepositoryDo.getLatitude());
            storeRepositoryVo.setCategoryId(storeRepositoryDo.getCategoryId());
            storeRepositoryVo.setCategoryName(storeRepositoryDo.getCategoryName());
            storeRepositoryVo.setFoodType(JSON.parseArray(storeRepositoryDo.getFoodTypes()));
            storeRepositoryVo.setBusinessStart(storeRepositoryDo.getBusinessStart());
            storeRepositoryVo.setBusinessEnd(storeRepositoryDo.getBusinessEnd());
            stores.add(storeRepositoryVo);
        }
        resultMap.put("stores", stores);
        resultMap.put("totalPages", pageList.getPages());
        resultMap.put("totalCount", pageList.getTotal());
        resultMap.put("currentPage", pageList.getCurrent());

        return Result.ok(resultMap);
    }

    /**
     * 查询配置给某个站点的店铺，有管理员或站长为该店铺配置的 拥挤
     * 接口调用场景
     * 1. 为站点配置的店铺，修改该店铺的佣金模式和金额前， 需要先查询该店铺的佣金模式和金额
     *
     * @return
     */
    @GetMapping("/queryStoreCommission")
    public Result<?> queryStoreCommissionByStoreId(
            @RequestParam("siteId") String siteId,
            @RequestParam("storeId") String storeId) {

        List<JxSiteStoreDo> list = jxSiteStoreMapper.selectList(new LambdaQueryWrapper<JxSiteStoreDo>()
                .eq(JxSiteStoreDo::getSiteId,siteId).eq(JxSiteStoreDo::getStoreId, storeId).eq(JxSiteStoreDo::getDelFlag, 0)
                .select(JxSiteStoreDo::getStorePrice, JxSiteStoreDo::getPlatFormCommissionType, JxSiteStoreDo::getPlatFormCommissionValue,
                    JxSiteStoreDo::getSiteMasterCommissionType, JxSiteStoreDo::getSiteMasterCommissionValue));

        JSONObject resultData = new JSONObject();
        if (list != null && list.size() > 0) {
            JxSiteStoreDo jxSiteStoreDo = list.get(0);
            resultData.put("storePrice", jxSiteStoreDo.getStorePrice());
            resultData.put("platFormCommissionType", jxSiteStoreDo.getPlatFormCommissionType());
            resultData.put("platFormCommissionValue", jxSiteStoreDo.getPlatFormCommissionValue());
            resultData.put("siteMasterCommissionType", jxSiteStoreDo.getSiteMasterCommissionType());
            resultData.put("siteMasterCommissionValue", jxSiteStoreDo.getSiteMasterCommissionValue());

            return Result.ok(resultData);
        } else {
            return Result.error("未找到该店铺的信息，请联系后台技术人员进行处理");
        }
    }

    /**
     * 保存修改后的店铺佣金模式和金额
     * 接口调用场景
     * 1. 管理员或站长 修改为某个站点配置的店铺的 拥挤模式和金额后，使用改接口保存修改后的佣金模式和金额
     *
     * @return
     */
    @PutMapping("/editStoreCommission")
    public Result<?> editStoreCommission(
            @RequestBody() JSONObject requestBody) {

        String siteId = requestBody.getString("siteId");
        String storeId = requestBody.getString("storeId");
        Integer storePrice = requestBody.getInteger("storePrice");
        Short platFormCommissionType = requestBody.getShort("platFormCommissionType");
        Integer platFormCommissionValue = requestBody.getInteger("platFormCommissionValue");
        Short siteMasterCommissionType = requestBody.getShort("siteMasterCommissionType");
        Integer siteMasterCommissionValue = requestBody.getInteger("siteMasterCommissionValue");

        JxSiteStoreDo jxSiteStoreDo = new JxSiteStoreDo();
        jxSiteStoreDo.setStorePrice(storePrice);
        jxSiteStoreDo.setPlatFormCommissionType(platFormCommissionType);
        jxSiteStoreDo.setPlatFormCommissionValue(platFormCommissionValue);
        jxSiteStoreDo.setSiteMasterCommissionType(siteMasterCommissionType);
        jxSiteStoreDo.setSiteMasterCommissionValue(siteMasterCommissionValue);

        int updateCount = jxSiteStoreMapper.update(jxSiteStoreDo, new LambdaQueryWrapper<JxSiteStoreDo>().eq(JxSiteStoreDo::getSiteId,siteId).eq(JxSiteStoreDo::getStoreId, storeId));
        if (updateCount == 1) {
            log.info("站点id: {}，店铺id：{} 合作价和佣金更新成功", siteId, storeId);
            return Result.ok("店铺合作价和佣金更新成功");
        } else {
            log.error("站点id: {}，店铺id：{} 合作价和佣金更新失败", siteId, storeId);
            return Result.ok("店铺合作价和佣金更新失败，请联系后台技术人员进行处理");
        }
    }

    /**
     * 使用场景
     * 1. 店铺&菜品编辑页面，操作列，【查看店铺】按钮，根据店铺id获取店铺详情，返回的信息仅包含店铺信息，不包含菜品信息
     * 2. 店铺&菜品编辑页面，操作列，【编辑店铺】按钮，该按钮仅编辑店铺基本信息，不涉及对菜品编辑，编辑店铺信息前，需要先调用此接口展示店铺信息
     * @param storeId
     * @return
     */
    @ApiOperation("查看店铺详情，仅获取店铺信息，不获取店铺下的菜品")
    @GetMapping("/queryStoreDetailByStoreId")
    public Result<?> queryStoreDetailByStoreId(
            @RequestParam("storeId") String storeId) {

        JxStoreRepositoryDo storeRepositoryDo = jxStoreRepositoryMapper.selectById(storeId);
        JxStoreRepositoryVo storeRepositoryVo = null;
        if (storeRepositoryDo != null) {

            storeRepositoryVo = new JxStoreRepositoryVo();
            storeRepositoryVo.setId(storeId);
            storeRepositoryVo.setStoreName(storeRepositoryDo.getStoreName());
            storeRepositoryVo.setStoreDescription(storeRepositoryDo.getStoreDescription());
            storeRepositoryVo.setLogo(storeRepositoryDo.getLogo());
            storeRepositoryVo.setLongitude(storeRepositoryDo.getLongitude());
            storeRepositoryVo.setLatitude(storeRepositoryDo.getLatitude());
            storeRepositoryVo.setMerchantName(storeRepositoryDo.getMerchantName());
            storeRepositoryVo.setMerchantIdNum(storeRepositoryDo.getMerchantIdNum());
            storeRepositoryVo.setMerchantPhone(storeRepositoryDo.getMerchantPhone());
            storeRepositoryVo.setMerchantWechatNum(storeRepositoryDo.getMerchantWechatNum());
            storeRepositoryVo.setStoreAddress(storeRepositoryDo.getStoreAddress());
            storeRepositoryVo.setCategoryId(storeRepositoryDo.getCategoryId());
            storeRepositoryVo.setCategoryName(storeRepositoryDo.getCategoryName());
            storeRepositoryVo.setFoodType(JSON.parseArray(storeRepositoryDo.getFoodTypes()));
            storeRepositoryVo.setBusinessStart(storeRepositoryDo.getBusinessStart());
            storeRepositoryVo.setBusinessEnd(storeRepositoryDo.getBusinessEnd());
        } else {
            return Result.error("店铺信息库表中，找不到id为 " + storeId + " 的店铺信息，请联系后台技术人员进行处理");
        }
        return Result.ok(storeRepositoryVo);
    }

    /**
     * siteId的作用是，排除已经为该站点挑选过的菜品
     * 接口适用场景
     * 1. 站点管理页面，挑选店铺后，点击店铺的 【挑选菜品】 按钮，弹出窗口，展示该店铺所有菜品，供管理员进行挑选；初次加载弹窗表格数据时，不用传递keyword
     * 2. 站点管理页面，挑选店铺后，点击店铺的 【挑选菜品】 按钮，弹出窗口，在弹窗中，输入搜索条件，搜索菜品，便于当店铺中菜品较多时，便于挑选
     * @param storeId
     * @param pageNo
     * @param pageSize
     * @return
     */
    @ApiOperation("继续为某个站点添加菜品时，加载某个店铺中的菜品列表，然后挑选菜品")
    @GetMapping("/queryFoodsByStoreId")
    public Result<?> queryFoodsByStoreId(
            @RequestParam("siteId") String siteId,
            @RequestParam("storeId") String storeId,
            @RequestParam(value = "keyword", required = false) String keyword,
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {
        Page<JxFoodRepositoryDo> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<JxFoodRepositoryDo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(JxFoodRepositoryDo::getDelFlag, 0).eq(JxFoodRepositoryDo::getState,"yes");

        List<JxSiteMenuDo> alreadySelectedFoods = jxSiteMenuMapper.selectList(new LambdaQueryWrapper<JxSiteMenuDo>().eq(JxSiteMenuDo::getSiteId, siteId).eq(JxSiteMenuDo::getStoreId, storeId).eq(JxSiteMenuDo::getDelFlag, 0).select(JxSiteMenuDo::getSiteId));
        List<String> alreadySelectedFoodIds = alreadySelectedFoods.stream().map(item -> item.getId()).collect(Collectors.toList());
        // 排除已经被站点挑选的菜品
        if (alreadySelectedFoodIds != null && alreadySelectedFoodIds.size() > 0) {
            lambdaQueryWrapper.notIn(JxFoodRepositoryDo::getId, alreadySelectedFoodIds);
        }
        if (keyword != null && !keyword.isEmpty()) {
            // select * from jx_food_repository where del_flag = 0 and state = 'yes' and id not in ('','') and food_name like '%keyword%';
            lambdaQueryWrapper.like(JxFoodRepositoryDo::getFoodName, keyword);
        }
        Page<JxFoodRepositoryDo> pageList = jxFoodRepositoryMapper.selectPage(page, lambdaQueryWrapper);
        List<JSONObject> formatedFoodList = new ArrayList<>();
        if (pageList != null && pageList.getRecords().size() > 0) {
            for (int i = 0; i < pageList.getRecords().size(); i++) {
                JxFoodRepositoryDo foodRepositoryDo = pageList.getRecords().get(i);
                JSONObject foodInfo = new JSONObject();
                // 菜品的 基本信息
                foodInfo.put("foodId", foodRepositoryDo.getId());
                foodInfo.put("foodName", foodRepositoryDo.getFoodName());
                foodInfo.put("description", foodRepositoryDo.getDescription());
                foodInfo.put("image", foodRepositoryDo.getImage());
                foodInfo.put("footType", foodRepositoryDo.getFoodTypeName()); // 店铺内的菜品类型

                // 在各个站点自定义的不同信息
                List<JxSiteMenuDo> list1 = jxSiteMenuMapper.selectList(new LambdaQueryWrapper<JxSiteMenuDo>().eq(JxSiteMenuDo::getSiteId, siteId).eq(JxSiteMenuDo::getFoodId, foodRepositoryDo.getId()));
                JxSiteMenuDo siteMenuDo = null;
                if (list1!= null && list1.size() > 0) {
                    siteMenuDo = list1.get(0);
                } else {
                    log.error("无法从站点菜单表中，查询到 菜品id: {} 的菜品", foodRepositoryDo.getId());
                    continue;
                }
                foodInfo.put("storePrice", siteMenuDo.getStorePrice());
                foodInfo.put("salePrice", siteMenuDo.getSalePrice());
                foodInfo.put("limitCount", siteMenuDo.getLimitCount());

                formatedFoodList.add(foodInfo);
            }
        }
        HashMap<String, Object> resultData = new HashMap<>();
        resultData.put("foods", formatedFoodList);
        resultData.put("totalPages", pageList.getPages());
        resultData.put("totalCount", pageList.getTotal());
        resultData.put("currentPage", pageList.getCurrent());
        return Result.ok(resultData);
    }

    @ApiOperation("编辑店铺基本信息")
    @PutMapping("/editStore")
    public Result<?> editStore(
            @RequestParam("storeId") String storeId, @RequestBody() JxStoreRepositoryVo storeRepositoryVo) throws Exception {

        JxStoreRepositoryDo storeRepositoryDo = buildStoreRepositoryInfo(storeRepositoryVo);
        storeRepositoryDo.setId(storeId);

        int count = jxStoreRepositoryMapper.updateById(storeRepositoryDo);

        if (count == 1) {
            log.info("店铺{} 信息更新成功", storeId);
            if (storeRepositoryVo.getLoginPassword() != null && !storeRepositoryVo.getLoginPassword().isEmpty()) {
                // 用于店主修改了登录密码，因此，当前正在使用的token需要作废，需要店主从商户端小程序上重新登录，生成新的token；
                // 清除redis中保存的 店铺的token，则下次店铺店主调用接口时，将返回 token失效
                redisUtil.del(MERCHANT_LOGIN_TOKEN_PREFIX);
                log.warn("店铺{} 登录密码重置成功，token失效，后续接口会返回401，小程序端应该跳转到 登录页面，让商户重新登录");
            }
            return Result.ok();
        } else {
            return Result.error("店铺信息更新失败，联系后台技术人员进行定位");
        }
    }


    /**
     * 根据店铺id删除店铺
     * 接口使用场景
     * 1. 店铺&菜品管理页面，表格中某个店铺【操作】列的 【删除】按钮调用此接口;
     * @param storeId
     * @return
     */
    @DeleteMapping("/deleteStoreById")
    public Result<?> deleteStoreById(@RequestParam("storeId") String storeId) {

        int deleteCount = jxStoreRepositoryMapper.deleteById(storeId);
        if (deleteCount >= 1) {
            log.info("店铺删除成功");
            return Result.ok("店铺删除成功");
        } else {
            log.error("店铺删除失败，请联系后台技术人员进行处理");
            return Result.error("店铺删除失败，请联系后台技术人员进行处理");
        }
    }

    @ApiOperation("根据店铺id，查询某个店铺的菜品分类，当添加菜品的时候需要使用此接口，为新添加的菜品选择分类")
    @GetMapping("/queryFoodTypeByStoreId")
    public Result<?> queryFoodTypeByStoreId(
            @RequestParam("storeId") String storeId) {

        List<String> foodTypes = jxStoreRepositoryMapper.queryFoodTypesByStoreId(storeId);
        JSONArray foodTypeArray = new JSONArray();
        if (foodTypes != null && foodTypes.size() > 0) {
            foodTypeArray = JSON.parseArray(foodTypes.get(0));
        }

        return Result.ok(foodTypeArray);
    }

    /**
     * 展示当前合作的所有店铺，作为菜品管理页面，所有店铺下拉列表的数据来源;
     * @return
     */
    @GetMapping("/queryAllStores")
    public Result<?> queryAllStores(
            @RequestParam("pageNo") Integer pageNo,
            @RequestParam("pageSize") Integer pageSize) {

        Page<JxStoreRepositoryDo> page = new Page<>(pageNo, pageSize);
        Page<JxStoreRepositoryDo> pageList = jxStoreRepositoryMapper.selectPage(page, new LambdaQueryWrapper<JxStoreRepositoryDo>().eq(JxStoreRepositoryDo::getDelFlag, 0));

        JSONObject resultData = new JSONObject();
        List<JSONObject> stores = new ArrayList<>();
        for (int k = 0 ; k < pageList.getRecords().size(); k ++) {

            JxStoreRepositoryDo storeRepositoryDo = pageList.getRecords().get(k);
            JSONObject formatedStoreInfo = new JSONObject();
            formatedStoreInfo.put("storeId", storeRepositoryDo.getId());
            formatedStoreInfo.put("storeName", storeRepositoryDo.getStoreName());

            stores.add(formatedStoreInfo);
        }

        resultData.put("stores", stores);
        resultData.put("totalPages", pageList.getPages());
        resultData.put("totalCount", pageList.getTotal());
        resultData.put("currentPage", pageList.getCurrent());

        return Result.ok(resultData);
    }
}
